#include "udp_client.hpp"
#include <cstring>
#include <pthread.h>



static void usage(string proc){
    cout << "Usage:\n\t" << proc << "serverip serverport\n"
         << endl;
}

//接收
void *recver(void* args){
    int sock = *static_cast<int *>(args);
    while(1){
        // 接收
        char buf[1024];
        //创建sockaddr_in结构体，存放服务器相关信息
        struct sockaddr_in tmp;
        socklen_t len = sizeof(tmp);
        //不用清空tmp，recvfrom读完数据会自动清空后面的区域
        //返回读取到元素个数
        int n = recvfrom(sock, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&tmp, &len);
        if (n > 0)
        {
            buf[n] = '\0';
            cout << "server echo# " << buf << endl;
        }
    }
}

// ./udp_client severip serverport
int main(int argc,char* argv[]){
    if(argc!=3){
        cerr << "argc != 3" << endl;
        usage(argv[0]);
        exit(USAGE_ERR);
    }
    string serverip = argv[1];
    uint16_t serverport = atoi(argv[2]);

    cout << " ↓ client ↓ " << endl;

    //init
    //1、创建socket接口，打开网络文件
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock<0){
        cerr << "create socket error" << endl;
        exit(SOCKET_ERR);
    }
    cout << "create socket success: " << sock << endl;
    //2、给客户端指明IP和Port，绑定
    //服务器需要手动bind，客户端不需要手动bind，OS自动帮助bind -- 客户端有很多不同进程，不能手动固定绑定某个端口，需要随机绑定
    //首次系统调用发送数据的时候，OS会在底层随机选择客户端口号+自己的ip进行bind和构建发送的数据报文

    //明确server
    //创建一个服务器套接字，用于存放相关信息
    struct sockaddr_in server;
    // bzero(&server, sizeof(server));
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    //server.sin_addr.s_addr = inet_addr(serverip.c_str());
    inet_aton(serverip.c_str(), &server.sin_addr);
    // start
    // 这里是阻塞式发送和接收，导致用户必须发送一次才能接收一次，需要改成多线程

    // while(1){

    //     //用户输入
    //     string message;
    //     cout << "Enter# ";
    //     getline(cin, message);
        

    //     //发送
    //     sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr *)&server, sizeof(server));

    //     // 接收
    //     char buf[1024];
    //     //创建sockaddr_in结构体，存放服务器相关信息
    //     struct sockaddr_in tmp;
    //     socklen_t len = sizeof(tmp);
    //     //不用清空tmp，recvfrom读完数据会自动清空后面的区域
    //     //返回读取到元素个数
    //     int n = recvfrom(sock, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&tmp, &len);
    //     if (n > 0)
    //     {
    //         buf[n] = '\0';
    //         cout << "server echo# " << buf << endl;
    //     }
    // }

    //创建一个只用来收消息的线程
    pthread_t tid;
    pthread_create(&tid, nullptr, recver, &sock);

    while(1){

        //用户输入
        string message;
        cerr << "Enter# ";
        getline(cin, message);
        

        //发送
        sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr *)&server, sizeof(server));

    }

    return 0;
}